use crate::ast::*;
use crate::error::{CompilerError, Result};
use inkwell::values::BasicValueEnum;

use super::LLVMBackend;

impl<'ctx> LLVMBackend<'ctx> {
    /// Generate statement
    pub(super) fn generate_statement(&mut self, stmt: &Statement) -> Result<()> {
        match stmt {
            Statement::Expression(expr) => {
                let _ = self.generate_expression(expr)?;
            }
            Statement::VariableDecl(var_decl) => {
                self.generate_variable_declaration(var_decl)?;
            }
            Statement::Assignment(assign_stmt) => {
                self.generate_assignment(assign_stmt)?;
            }
            Statement::Return(return_stmt) => {
                self.generate_return_statement(return_stmt)?;
            }
            Statement::If(if_stmt) => {
                self.generate_if_statement(if_stmt)?;
            }
            Statement::Block(block_stmt) => {
                self.generate_block_statement(block_stmt)?;
            }
            Statement::Match(match_stmt) => {
                self.generate_match_statement(match_stmt)?;
            }
            Statement::Defer(defer_stmt) => {
                self.generate_defer_statement(defer_stmt)?;
            }
            Statement::Recover(recover_stmt) => {
                self.generate_recover_statement(recover_stmt)?;
            }
            Statement::For(for_stmt) => {
                self.generate_for_statement(for_stmt)?;
            }
            Statement::While(while_stmt) => {
                self.generate_while_statement(while_stmt)?;
            }
            _ => {
                // Other statement types not yet implemented
            }
        }
        Ok(())
    }

    /// Generate return statement
    pub(super) fn generate_return_statement(&mut self, return_stmt: &ReturnStmt) -> Result<()> {
        // Execute all pending defer statements before returning
        self.execute_all_defer_statements()?;

        if let Some(ref value) = return_stmt.value {
            let mut return_value = self.generate_expression(value)?;

            if let Some(expected_type) = self.current_function_return_type.clone() {
                let inferred_type = self.infer_expression_type(value);
                return_value =
                    self.coerce_value_to_type(return_value, inferred_type.as_ref(), &expected_type)?;
            }

            // Get the expected return type from the function
            if let Some(func) = self.current_function {
                let func_return_type = func.get_type().get_return_type();

                // Cast return value to match function return type if needed
                if let Some(expected_type) = func_return_type {
                    if return_value.get_type() != expected_type {
                        return_value = self.cast_value_to_type(return_value, expected_type)?;
                    }
                }
            }

            let _ = self.builder.build_return(Some(&return_value));
        } else {
            let _ = self.builder.build_return(None);
        }
        Ok(())
    }

    /// Generate block statement
    pub(super) fn generate_block_statement(&mut self, block_stmt: &BlockStmt) -> Result<()> {
        self.enter_scope();
        for stmt in &block_stmt.statements {
            self.generate_statement(stmt)?;
        }
        self.exit_scope()?;
        Ok(())
    }

    /// Generate defer statement
    pub(super) fn generate_defer_statement(&mut self, defer_stmt: &DeferStmt) -> Result<()> {
        self.add_defer_to_current_scope(defer_stmt.expr.clone());
        Ok(())
    }

    /// Generate recover statement
    /// Registers a recover handler that can catch panics occurring after this statement
    /// Creates an "after_recover" block where execution continues when panic is caught
    /// This block is OUTSIDE the recover protection region, so it won't contain panic code
    pub(super) fn generate_recover_statement(
        &mut self,
        recover_stmt: &stmt::RecoverStmt,
    ) -> Result<()> {
        let func = self.current_function.ok_or_else(|| {
            CompilerError::internal("Cannot create recover block outside function")
        })?;

        // Create an "after_recover" block where execution continues when panic is caught
        // This block is OUTSIDE the recover protection region
        // It will be placed AFTER all code in the recover protection region (including panic)
        let after_recover_block = self.context.append_basic_block(func, "after_recover");

        // Register the recover handler and its after block
        self.recover_stack.push(recover_stmt.clone());
        self.recover_after_blocks.push(after_recover_block);

        // For normal execution, we continue in the current block
        // Code after recover statement will be generated in the current block
        // When panic is caught, execution will jump to after_recover_block (skipping current block and subsequent code)
        // So we DON'T branch to after_recover_block here - it's only for panic recovery

        Ok(())
    }

    /// Generate variable declaration
    pub(super) fn generate_variable_declaration(
        &mut self,
        var_decl: &VariableDeclStmt,
    ) -> Result<()> {
        let var_name = &var_decl.name;

        // Infer type from initializer if not provided
        let var_type = if let Some(ref explicit_type) = var_decl.var_type {
            Some(explicit_type.clone())
        } else if let Some(ref init_expr) = var_decl.initializer {
            // Infer type from initializer expression
            self.infer_expression_type(init_expr)
                .ok_or_else(|| {
                    // Provide more context about the expression that failed
                    let expr_info = match init_expr {
                        Expression::MethodCall(mc) => format!(
                            "method call: {}.{}()",
                            match &*mc.object {
                                Expression::Variable(v) => v.clone(),
                                _ => "?".to_string(),
                            },
                            mc.method
                        ),
                        Expression::Variable(v) => format!("variable: {}", v),
                        Expression::Call(c) => format!("call: {:?}", c),
                        _ => format!("{:?}", init_expr),
                    };
                    CompilerError::internal(&format!(
                        "Cannot infer type from initializer expression: {}",
                        expr_info
                    ))
                })
                .map(Some)?
        } else {
            return Err(CompilerError::internal(
                "Variable declaration requires either type or initializer",
            ));
        };

        // Handle rc<T> and weak<T> types specially
        if let Some(Type::Rc(_inner_type)) = &var_type {
            return self.handle_rc_variable_declaration(
                var_name,
                &var_type,
                var_decl.initializer.as_ref(),
            );
        }

        if let Some(Type::Weak(_inner_type)) = &var_type {
            return self.handle_weak_variable_declaration(
                var_name,
                &var_type,
                var_decl.initializer.as_ref(),
            );
        }

        // For slice types, we need to check if this is a stack or heap allocation
        if let Some(Type::Vec(_vector_type)) = &var_type {
            // Track stack-allocated slices for automatic cleanup
            self.stack_slices.push(var_name.clone());
        }

        // Generate the initial value
        let mut value = if let Some(ref init_expr) = var_decl.initializer {
            // Check if we need to auto-wrap value in Option::Some for Dart-style nullable types
            // e.g., int? a = 10; should auto-wrap to Option::Some(10)
            let init_type = self.infer_expression_type(init_expr);
            let needs_option_wrap = if let Some(Type::Option(option_type)) = &var_type {
                // Variable type is Option<T>
                // Check if initializer is NOT already Some/None/Option expression
                let is_not_option_expr = !matches!(
                    init_expr,
                    Expression::Path(path) if path.segments.len() == 2 &&
                        (path.segments[0] == "Option" || path.segments[0] == "Some" || path.segments[0] == "None")
                ) && !matches!(
                    init_expr,
                    Expression::Call(call) if matches!(&*call.callee,
                        Expression::Path(path) if path.segments.len() == 2 &&
                            (path.segments[0] == "Option" || path.segments[0] == "Some" || path.segments[0] == "None")
                    )
                );

                // Check if initializer type matches Option's Some type
                if is_not_option_expr {
                    if let Some(init_type) = &init_type {
                        // Check if init_type matches option_type.some_type
                        // If they match, we can auto-wrap
                        match init_type {
                            Type::Option(_) => false, // Already an Option, don't wrap
                            _ => {
                                // Check if types are compatible (init_type matches option_type.some_type)
                                // Use a simple type equality check for now
                                // TODO: Add proper type compatibility checking
                                *init_type == *option_type.some_type
                            }
                        }
                    } else {
                        false
                    }
                } else {
                    false
                }
            } else {
                false
            };

            if needs_option_wrap {
                // Auto-wrap: create Option::Some(init_expr)
                if let Some(Type::Option(_option_type)) = &var_type {
                    let some_path = Expression::Path(PathExpr {
                        segments: vec!["Option".to_string(), "Some".to_string()],
                        location: init_expr.location(),
                    });
                    let wrapped_expr = Expression::Call(CallExpr {
                        callee: Box::new(some_path),
                        arguments: vec![init_expr.clone()],
                        type_args: Vec::new(),
                        resolved: None,
                        location: init_expr.location(),
                    });
                    self.generate_expression(&wrapped_expr)?
                } else {
                    self.generate_expression(init_expr)?
                }
            } else {
                // Special handling for slice assignments: perform deep copy if assigning from another variable
                if let Some(Type::Vec(vector_type)) = &var_type {
                    // Check if the initializer is a variable reference (which means we need deep copy)
                    let needs_deep_copy = matches!(init_expr, Expression::Variable(_));

                    if needs_deep_copy {
                        // Generate the source value first
                        let source_value = self.generate_expression(init_expr)?;
                        // Perform deep copy
                        self.deep_copy_slice(source_value, vector_type)?
                    } else {
                        // For slice literals or other expressions, generate normally
                        self.generate_expression(init_expr)?
                    }
                } else {
                    self.generate_expression(init_expr)?
                }
            }
        } else {
            // If no initializer, generate zero value
            if let Some(ref vtype) = var_type {
                self.generate_zero_value(vtype)?
            } else {
                return Err(CompilerError::internal(
                    "Variable declaration requires either type or initializer",
                ));
            }
        };

        let inferred_type = var_decl
            .initializer
            .as_ref()
            .and_then(|expr| self.infer_expression_type(expr));

        if let Some(ref target_type) = var_type {
            value = self.coerce_value_to_type(value, inferred_type.as_ref(), target_type)?;
        }

        // Cast value to target type if needed (for type compatibility)
        if let Some(ref target_type) = var_type {
            let target_llvm_type = self.nrc_type_to_llvm_type(&Some(target_type.clone()))?;
            value = self.cast_value_to_type(value, target_llvm_type)?;
        }

        // Allocate space for the variable on the stack
        let llvm_type = self.nrc_type_to_llvm_type(&var_type)?;
        let alloca = self.builder.build_alloca(llvm_type, var_name)?;

        // Store the initial value
        let _ = self.builder.build_store(alloca, value);

        // Track the variable in the variable map (store the pointer)
        self.variable_map.insert(var_name.clone(), alloca.into());

        // Track the variable type
        if let Some(vtype) = var_type {
            self.variable_type_map
                .insert(var_name.clone(), vtype.clone());

            // Check if this is a struct type with init and drop methods
            let struct_name = match &vtype {
                Type::Struct(struct_type) => Some(&struct_type.name),
                Type::Generic(name) => Some(name),
                _ => None,
            };

            if let Some(name) = struct_name {
                if let Some(struct_decl) = self.struct_declarations.get(name) {
                    if let Some(drop_method) = struct_decl.get_method("drop") {
                        if drop_method.is_destructor() {
                            // Add automatic defer for drop method
                            self.add_automatic_drop_defer(var_name, name)?;
                        }
                    }
                }
            }
        }

        Ok(())
    }

    /// Generate assignment statement
    pub(super) fn generate_assignment(&mut self, assign_stmt: &AssignmentStmt) -> Result<()> {
        match &assign_stmt.target {
            AssignmentTarget::Variable(var_name) => {
                // Check if variable exists and clone it to avoid borrow conflicts
                let var_ptr = self
                    .variable_map
                    .get(var_name)
                    .ok_or_else(|| {
                        CompilerError::internal(&format!("Undefined variable: {}", var_name))
                    })?
                    .clone();

                // Handle rc<T>, weak<T>, and slice assignments specially
                // Clone the variable type to avoid borrow conflicts
                let var_type_clone = self.variable_type_map.get(var_name).cloned();
                if let Some(ref var_type) = var_type_clone {
                    match var_type {
                        Type::Rc(_) => {
                            return self.handle_rc_assignment(var_name, &assign_stmt.value);
                        }
                        Type::Weak(_) => {
                            return self.handle_weak_assignment(var_name, &assign_stmt.value);
                        }
                        Type::Vec(vector_type) => {
                            // For slice assignments from variables, perform deep copy
                            let needs_deep_copy =
                                matches!(&assign_stmt.value, Expression::Variable(_));

                            let new_value = if needs_deep_copy {
                                let source_value = self.generate_expression(&assign_stmt.value)?;
                                self.deep_copy_slice(source_value, vector_type)?
                            } else {
                                self.generate_expression(&assign_stmt.value)?
                            };

                            // Get the pointer value
                            let ptr = match var_ptr {
                                BasicValueEnum::PointerValue(p) => p,
                                _ => {
                                    return Err(CompilerError::internal(
                                        "Variable is not a pointer",
                                    ))
                                }
                            };

                            // Store the new value
                            let _ = self.builder.build_store(ptr, new_value);
                            return Ok(());
                        }
                        Type::Reference(ref_type)
                            if self
                                .trait_name_from_type(&ref_type.referenced_type)
                                .is_none() =>
                        {
                            // Check if the assignment is a reference reassignment: ref = &other_var
                            if let Expression::Unary(unary_expr) = &assign_stmt.value {
                                if unary_expr.operator == crate::ast::expr::UnaryOp::AddrOf {
                                    // This is a reference reassignment: ref = &other_var
                                    // We need to update the reference variable to point to the new address

                                    // Get the reference variable pointer
                                    let ref_ptr = match var_ptr {
                                        BasicValueEnum::PointerValue(p) => p,
                                        _ => {
                                            return Err(CompilerError::internal(
                                                "Reference variable is not a pointer",
                                            ))
                                        }
                                    };

                                    // Get the address of the target variable directly
                                    if let Expression::Variable(target_var_name) =
                                        &*unary_expr.operand
                                    {
                                        // Get the target variable's alloca pointer
                                        if let Some(target_var_ptr) =
                                            self.variable_map.get(target_var_name)
                                        {
                                            let target_ptr = match target_var_ptr {
                                                BasicValueEnum::PointerValue(p) => *p,
                                                _ => {
                                                    return Err(CompilerError::internal(
                                                        "Target variable must be a pointer",
                                                    ))
                                                }
                                            };

                                            // Store the new address in the reference variable
                                            let _ = self.builder.build_store(ref_ptr, target_ptr);
                                        } else {
                                            return Err(CompilerError::internal(&format!(
                                                "Target variable not found: {}",
                                                target_var_name
                                            )));
                                        }
                                    } else {
                                        return Err(CompilerError::internal(
                                            "Reference reassignment only supports simple variables",
                                        ));
                                    }
                                    return Ok(());
                                }
                            }

                            // This is a value assignment: ref = value
                            // We need to store the value at the address that the reference points to

                            // Get the reference variable pointer
                            let ref_ptr = match var_ptr {
                                BasicValueEnum::PointerValue(p) => p,
                                _ => {
                                    return Err(CompilerError::internal(
                                        "Reference variable is not a pointer",
                                    ))
                                }
                            };

                            // Load the address that the reference points to
                            let target_ptr = self.builder.build_load(
                                self.context
                                    .i8_type()
                                    .ptr_type(inkwell::AddressSpace::default()),
                                ref_ptr,
                                &format!("{}_target", var_name),
                            )?;

                            let target_ptr = match target_ptr {
                                BasicValueEnum::PointerValue(p) => p,
                                _ => {
                                    return Err(CompilerError::internal(
                                        "Reference should point to a valid address",
                                    ))
                                }
                            };

                            // Generate the new value
                            let new_value = self.generate_expression(&assign_stmt.value)?;

                            // Store the new value at the target address
                            let _ = self.builder.build_store(target_ptr, new_value);
                            return Ok(());
                        }
                        _ => {}
                    }
                }

                // Generate the new value with auto-wrap for Dart-style nullable types
                let value_type_hint = self.infer_expression_type(&assign_stmt.value);
                let new_value = {
                    // Check if we need to auto-wrap value in Option::Some for Dart-style nullable types
                    // e.g., int? a = 10; should auto-wrap to Option::Some(10)
                    let value_type = value_type_hint.clone();
                    let needs_option_wrap = if let Some(Type::Option(option_type)) = &var_type_clone
                    {
                        // Variable type is Option<T>
                        // Check if initializer is NOT already Some/None/Option expression
                        let is_not_option_expr = !matches!(
                            &assign_stmt.value,
                            Expression::Path(path) if path.segments.len() == 2 &&
                                (path.segments[0] == "Option" || path.segments[0] == "Some" || path.segments[0] == "None")
                        ) && !matches!(
                            &assign_stmt.value,
                            Expression::Call(call) if matches!(&*call.callee,
                                Expression::Path(path) if path.segments.len() == 2 &&
                                    (path.segments[0] == "Option" || path.segments[0] == "Some" || path.segments[0] == "None")
                            )
                        );

                        // Check if initializer type matches Option's Some type
                        if is_not_option_expr {
                            if let Some(init_type) = &value_type {
                                // Check if init_type matches option_type.some_type
                                match init_type {
                                    Type::Option(_) => false, // Already an Option, don't wrap
                                    _ => {
                                        // Check if types are compatible (init_type matches option_type.some_type)
                                        *init_type == *option_type.some_type
                                    }
                                }
                            } else {
                                false
                            }
                        } else {
                            false
                        }
                    } else {
                        false
                    };

                    if needs_option_wrap {
                        // Auto-wrap: create Option::Some(assign_stmt.value)
                        if let Some(Type::Option(_option_type)) = &var_type_clone {
                            let some_path = Expression::Path(PathExpr {
                                segments: vec!["Option".to_string(), "Some".to_string()],
                                location: assign_stmt.value.location(),
                            });
                            let wrapped_expr = Expression::Call(CallExpr {
                                callee: Box::new(some_path),
                                arguments: vec![assign_stmt.value.clone()],
                                type_args: Vec::new(),
                                resolved: None,
                                location: assign_stmt.value.location(),
                            });
                            self.generate_expression(&wrapped_expr)?
                        } else {
                            self.generate_expression(&assign_stmt.value)?
                        }
                    } else {
                        self.generate_expression(&assign_stmt.value)?
                    }
                };

                let new_value = if let Some(ref target_type) = var_type_clone {
                    self.coerce_value_to_type(new_value, value_type_hint.as_ref(), target_type)?
                } else {
                    new_value
                };

                // Get the pointer value
                let ptr = match var_ptr {
                    BasicValueEnum::PointerValue(p) => p,
                    _ => return Err(CompilerError::internal("Variable is not a pointer")),
                };

                // Store the new value
                let _ = self.builder.build_store(ptr, new_value);
                Ok(())
            }
            AssignmentTarget::FieldAccess(field_access) => {
                // Handle struct field assignment
                let struct_ptr = match &field_access.object {
                    Expression::Variable(var_name) => {
                        let var_value = self.variable_map.get(var_name).ok_or_else(|| {
                            CompilerError::internal(&format!("Undefined variable: {}", var_name))
                        })?;

                        // Check if this is a reference type that needs auto-dereferencing
                        if let Some(var_type) = self.variable_type_map.get(var_name) {
                            match var_type {
                                Type::Reference(_) => {
                                    // For reference types, we need to load the pointer first
                                    let alloca_ptr = var_value.into_pointer_value();
                                    let ptr_value = self.builder.build_load(
                                        self.context
                                            .i8_type()
                                            .ptr_type(inkwell::AddressSpace::default()),
                                        alloca_ptr,
                                        &format!("{}_ptr", var_name),
                                    )?;

                                    if let BasicValueEnum::PointerValue(ptr) = ptr_value {
                                        ptr
                                    } else {
                                        return Err(CompilerError::internal(
                                            "Expected pointer value for reference",
                                        ));
                                    }
                                }
                                _ => {
                                    // For non-reference types, use existing logic
                                    match var_value {
                                        BasicValueEnum::PointerValue(ptr) => *ptr,
                                        _ => {
                                            return Err(CompilerError::internal(
                                                "Expected pointer value for struct",
                                            ))
                                        }
                                    }
                                }
                            }
                        } else {
                            // Fallback to existing logic
                            match var_value {
                                BasicValueEnum::PointerValue(ptr) => *ptr,
                                _ => {
                                    return Err(CompilerError::internal(
                                        "Expected pointer value for struct",
                                    ))
                                }
                            }
                        }
                    }
                    _ => {
                        return Err(CompilerError::internal(
                            "Field access assignment target must be a variable",
                        ))
                    }
                };

                // Find the struct type to get field index
                let field_name = &field_access.field;
                let struct_decl =
                    self.resolve_struct_for_field_access(&field_access.object, field_name)
                        .ok_or_else(|| {
                    CompilerError::internal(&format!(
                        "Struct with field '{}' not found",
                        field_name
                    ))
                })?;

                let field_index = struct_decl
                    .fields
                    .iter()
                    .position(|f| &f.name == field_name)
                    .ok_or_else(|| {
                        CompilerError::internal(&format!("Field '{}' not found", field_name))
                    })?;

                // Build struct type from declaration
                let mut field_types = Vec::new();
                for field in &struct_decl.fields {
                    let field_llvm_type =
                        self.nrc_type_to_llvm_type(&Some(field.field_type.clone()))?;
                    field_types.push(field_llvm_type.into());
                }
                let struct_type = self.context.struct_type(&field_types, false);

                // Get field pointer
                let field_ptr = self.builder.build_struct_gep(
                    struct_type,
                    struct_ptr,
                    field_index as u32,
                    &format!("{}_ptr", field_name),
                )?;

                // Generate and store the new value
                let new_value = self.generate_expression(&assign_stmt.value)?;
                let _ = self.builder.build_store(field_ptr, new_value);

                Ok(())
            }
            AssignmentTarget::IndexAccess(index_access) => {
                // Handle slice element assignment
                let array_value = match &index_access.object {
                    Expression::Variable(var_name) => self
                        .variable_map
                        .get(var_name)
                        .ok_or_else(|| {
                            CompilerError::internal(&format!("Undefined variable: {}", var_name))
                        })?
                        .clone(),
                    _ => {
                        return Err(CompilerError::internal(
                            "Index access assignment only supports variables",
                        ))
                    }
                };

                // Generate the index
                let index = self.generate_expression(&index_access.index)?;
                let index_int = match index {
                    BasicValueEnum::IntValue(i) => i,
                    _ => return Err(CompilerError::internal("Index must be an integer")),
                };

                // Get the type of the array
                let array_type = match &index_access.object {
                    Expression::Variable(var_name) => self.variable_type_map.get(var_name).cloned(),
                    _ => None,
                };

                match array_type {
                    Some(Type::Vec(vector_type)) => {
                        // Load slice struct
                        let slice_ptr = match array_value {
                            BasicValueEnum::PointerValue(p) => p,
                            _ => {
                                return Err(CompilerError::internal(
                                    "Slice variable must be a pointer",
                                ))
                            }
                        };

                        let slice_struct_type =
                            self.nrc_type_to_llvm_type(&Some(Type::Vec(vector_type.clone())))?;

                        // Get the data pointer (field 0)
                        let data_ptr_ptr = self.builder.build_struct_gep(
                            slice_struct_type,
                            slice_ptr,
                            0,
                            "data_ptr_ptr",
                        )?;
                        let ptr_type = self
                            .context
                            .i8_type()
                            .ptr_type(inkwell::AddressSpace::default());
                        let data_ptr =
                            self.builder
                                .build_load(ptr_type, data_ptr_ptr, "data_ptr")?;
                        let data_ptr = match data_ptr {
                            BasicValueEnum::PointerValue(p) => p,
                            _ => {
                                return Err(CompilerError::internal(
                                    "Data pointer must be a pointer",
                                ))
                            }
                        };

                        // Calculate element pointer
                        let element_ptr = unsafe {
                            self.builder.build_gep(
                                self.nrc_type_to_llvm_type(&Some(
                                    *vector_type.element_type.clone(),
                                ))?,
                                data_ptr,
                                &[index_int],
                                "element_ptr",
                            )?
                        };

                        // Generate and store the new value
                        let new_value = self.generate_expression(&assign_stmt.value)?;
                        let _ = self.builder.build_store(element_ptr, new_value);
                    }
                    Some(Type::Array(array_type)) => {
                        // Handle fixed-size array assignment
                        let array_ptr = match array_value {
                            BasicValueEnum::PointerValue(p) => p,
                            _ => {
                                return Err(CompilerError::internal(
                                    "Array variable must be a pointer",
                                ))
                            }
                        };

                        // Get element pointer
                        let zero = self.context.i32_type().const_int(0, false);
                        let element_ptr = unsafe {
                            self.builder.build_gep(
                                self.nrc_type_to_llvm_type(&Some(Type::Array(array_type.clone())))?,
                                array_ptr,
                                &[zero, index_int],
                                "element_ptr",
                            )?
                        };

                        // Generate and store the new value
                        let new_value = self.generate_expression(&assign_stmt.value)?;
                        let _ = self.builder.build_store(element_ptr, new_value);
                    }
                    _ => {
                        return Err(CompilerError::internal(
                            "Index access assignment only supports arrays and slices",
                        ))
                    }
                }

                Ok(())
            }
            AssignmentTarget::Deref(deref_expr) => {
                // Handle pointer dereference assignment: *ptr = value
                let ptr_value = self.generate_expression(deref_expr)?;
                let ptr = match ptr_value {
                    BasicValueEnum::PointerValue(p) => p,
                    _ => {
                        return Err(CompilerError::internal(
                            "Dereference target must be a pointer",
                        ))
                    }
                };

                let new_value = self.generate_expression(&assign_stmt.value)?;
                let _ = self.builder.build_store(ptr, new_value);
                Ok(())
            }
        }
    }

    /// Add automatic defer for drop method when a struct variable is declared
    fn add_automatic_drop_defer(&mut self, var_name: &str, struct_name: &str) -> Result<()> {
        // Create a method call expression for the drop method
        // Use the full method name format: {TypeName}.drop
        let full_method_name = format!("{}.drop", struct_name);
        let drop_call = Expression::MethodCall(MethodCallExpr {
            object: Box::new(Expression::Variable(var_name.to_string())),
            method: full_method_name,
            type_args: vec![],
            arguments: vec![],
            location: crate::error::Location::new(0, 0, 0),
        });

        // Create a defer statement
        let defer_stmt = DeferStmt {
            expr: drop_call,
            location: crate::error::Location::new(0, 0, 0),
        };

        // Add to current scope
        self.add_defer_to_current_scope(defer_stmt.expr.clone());

        Ok(())
    }
}
